package com.hd123.rumba.gwt.widget2.client.misc;

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

import com.google.gwt.dom.client.Document;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * 只遮住一个控件区域的半透明遮罩，支持多层遮罩。
 * 
 * @author LiQi
 * 
 */
public class RWidgetMask extends HTMLPanel {

  public static final String STYLENAME = "rb-Mask";

  /** 多层遮罩堆栈 */
  private static Map<Widget, Stack<RWidgetMask>> maskStacks = new HashMap();

  /** 要遮住的控件 */
  private Widget widget;

  /**
   * @param widget
   *          要遮住的控件
   */
  protected RWidgetMask(Widget widget) {
    super("");
    setStyleName(STYLENAME);
    this.widget = widget;
    Window.addResizeHandler(new WindowHandler());
  }

  /**
   * 在指定的控件上显示遮罩
   * 
   * @param widget
   */
  public static void show(Widget widget) {
    // widget对应的堆栈
    Stack stack = maskStacks.get(widget);
    if (stack == null) {
      stack = new Stack();
      maskStacks.put(widget, stack);
    }

    RWidgetMask mask = new RWidgetMask(widget);
    stack.push(mask);
    mask.doShow();
  }

  /**
   * 隐藏指定的控件上的遮罩，如果存在多层遮罩，则只隐藏最上层的一个
   * 
   * @param widget
   */
  public static void hide(Widget widget) {
    // widget对应的堆栈
    Stack<RWidgetMask> stack = maskStacks.get(widget);
    if (stack == null || stack.isEmpty())
      return;

    RWidgetMask mask = stack.pop();
    mask.doHide();
  }

  /**
   * 隐藏指定的控件上的遮罩，如果存在多层遮罩，则全部隐藏
   * 
   */
  public static void hideAll(Widget widget) {
    Stack<RWidgetMask> stack = maskStacks.get(widget);
    if (stack == null)
      return;

    while (!stack.isEmpty()) {
      RWidgetMask mask = stack.pop();
      mask.doHide();
    }
  }

  /**
   * 控件上是否正在显示遮罩
   * 
   * @param widget
   * @return
   */
  public static boolean isShowing(Widget widget) {
    Stack<RWidgetMask> stack = maskStacks.get(widget);
    return stack != null && !stack.isEmpty();
  }

  /**
   * 要遮住的控件
   * 
   * @return
   */
  protected Widget getWidget() {
    return widget;
  }

  /**
   * 显示遮罩
   * 
   */
  protected void doShow() {
    if (getParent() != null)
      return;

    setWidth(widget.getOffsetWidth() + "px");
    setHeight(widget.getOffsetHeight() + "px");
    RootPanel.get().add(this, widget.getAbsoluteLeft(), widget.getAbsoluteTop());
  }

  /**
   * 隐藏遮罩
   * 
   */
  protected void doHide() {
    RootPanel.get().remove(this);
  }

  /**
   * 窗口事件处理，保证在窗口改变大小时遮罩能正确显示
   * 
   * @author LiQi
   * 
   */
  private class WindowHandler implements ResizeHandler {
    public void onResize(ResizeEvent event) {
      if (getParent() == null)
        return;
      DeferredCommand.addCommand(new Command() {
        public void execute() {
          setWidth(widget.getOffsetWidth() + "px");
          setHeight(widget.getOffsetHeight() + "px");
          DOM.setStyleAttribute(getElement(), "left", widget.getAbsoluteLeft()
              - Document.get().getBodyOffsetLeft() + "px");
          DOM.setStyleAttribute(getElement(), "top", widget.getAbsoluteTop()
              - Document.get().getBodyOffsetTop() + "px");
        }
      });
    }
  }
}
